package com.meshnetics.gb.stack.mac.primitives;

import com.meshnetics.gb.stack.core.event.StackConfirm;
import com.meshnetics.gb.stack.core.event.StackEvent;
import com.meshnetics.gb.stack.core.event.StackEventType;
import com.meshnetics.gb.stack.core.layer.StackLayer;
import com.meshnetics.gb.stack.mac.RadioMACStackLayer;
import com.meshnetics.gb.stack.mac.type.MACStatus;
import com.meshnetics.gb.stack.mac.type.TypeMACStatus;
import com.meshnetics.gb.type.impl.ByteUtils;
import com.meshnetics.gb.type.impl.zcl.TypeUInt;
import com.meshnetics.gb.type.impl.zcl.UInt;

import java.nio.ByteBuffer;

/**
 * WRITE DESCRIPTION HERE
 *
 * @author AKovylin
 */
public class MACAssociateConfirm extends StackConfirm implements MACReplyOnCommand {
    public static final byte CODE = 0x46;

    private static final byte[] ALLOWED_STATUSES = new byte[]{
            MACStatus.SUCCESS.getCode(),
            MACStatus.PAN_AT_CAPACITY.getCode(),
            MACStatus.PAN_ACCESS_DENIED.getCode(),
            MACStatus.CHANNEL_ACCESS_FAILURE.getCode(),
            MACStatus.NO_ACK.getCode(),
            MACStatus.NO_DATA.getCode(),
            MACStatus.UNAVAILABLE_KEY.getCode(),
            MACStatus.FAILED_SECURITY_CHECK.getCode(),
            MACStatus.INVALID_PARAMETER.getCode(),
    };

    private final UInt assocShortAddr;

    public MACAssociateConfirm(ByteBuffer bb, RadioMACStackLayer layer) {
        super("macAssociateConfirm", StackEventType.LME_TYPE, null, null, layer);
        ByteUtils.ensureNotNull(bb);
        ByteUtils.ensureCapacity(bb, 3);
        this.assocShortAddr = (UInt) TypeUInt.UINT_16.deserialize(bb);
        MACStatus status = (MACStatus) TypeMACStatus.TYPE.deserialize(bb);
        Utils.checkStatus(status, ALLOWED_STATUSES);
        setStatus(status);
        if (bb.remaining() > 0) {
            throw new IllegalArgumentException("unexpected content of ByteBuffer, " + bb.remaining() + " bytes left");
        }
    }

    public MACAssociateConfirm(MACStatus status, short assocShortAddr) {
        this(status, new Short(assocShortAddr));
    }

    public MACAssociateConfirm(MACStatus status, Short assocShortAddr) {
        this(status, (UInt) TypeUInt.UINT_16.fromObject(assocShortAddr));
    }

    public MACAssociateConfirm(MACStatus status, UInt assocShortAddr) {
        this(status, assocShortAddr, null);
    }

    public MACAssociateConfirm(MACStatus status, UInt assocShortAddr, StackLayer source) {
        super("macAssociateConfirm", StackEventType.LME_TYPE, null, null, source);
        if (status == null) {
            throw new NullPointerException("status is null");
        }
        if (assocShortAddr == null) {
            throw new NullPointerException("assocShortAddr is null");
        }
        Utils.checkStatus(status, ALLOWED_STATUSES);
        setStatus(status);
        this.assocShortAddr = assocShortAddr.convert(TypeUInt.UINT_16);
    }

    public Short getAssocShortAddr() {
        return (Short) assocShortAddr.toObject();
    }

    public UInt getAssocShortAddrType() {
        return assocShortAddr;
    }

    public boolean isReplyOn(StackEvent se) {
        return se instanceof MACAssociateRequest;
    }

    public String toString() {
        return getName() + '(' + getStatus() + ',' + assocShortAddr + ')';
    }
}
